package com.kmzx.one.project.config.listener;


import com.kmzx.one.common.constants.UpMode;
import com.kmzx.one.common.utils.UUIDGenerator;
import com.kmzx.one.project.entity.UserExchangeRate;
import com.kmzx.one.project.entity.UserInvite;
import com.kmzx.one.project.entity.UserOrder;
import com.kmzx.one.project.entity.UserProfit;
import com.kmzx.one.project.entity.UserRank;
import com.kmzx.one.project.entity.UserRankDetail;
import com.kmzx.one.project.entity.UserRankHistory;
import com.kmzx.one.project.events.SelfAndUpEvent;
import com.kmzx.one.project.events.UserRewardEvent;
import com.kmzx.one.project.mapper.CustomerMapper;
import com.kmzx.one.project.mapper.UserExchangeRateMapper;
import com.kmzx.one.project.mapper.UserInviteMapper;
import com.kmzx.one.project.mapper.UserOrderMapper;
import com.kmzx.one.project.mapper.UserProfitMapper;
import com.kmzx.one.project.mapper.UserRankMapper;
import com.kmzx.one.project.others.dso.UserRankDso;
import com.kmzx.one.project.others.dto.UserRankInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Component("userRewardListener")
public class UserRewardListener {

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private UserProfitMapper userProfitMapper;

    @Autowired
    private UserRankMapper userRankMapper;

    @Autowired
    private UserInviteMapper userInviteMapper;

    @Autowired
    private UserOrderMapper userOrderMapper;

    @Autowired
    private UserExchangeRateMapper userExchangeRateMapper;

    @Autowired
    ApplicationContext applicationContext;

    private static Logger logger = LoggerFactory.getLogger(UserRewardListener.class);

    @Async
    @EventListener(classes = {UserRewardEvent.class})
    @Transactional(rollbackFor = Exception.class)
    public void defaultUserRewardEvent(UserRewardEvent userRewardEvent) {

        String userId = userRewardEvent.getUserId();
        String orderId = userRewardEvent.getOrderId();
        int inOrOut = userRewardEvent.getInOrOut();
//        UserOrder order = userOrderMapper.selectByPrimaryKey(orderId);
        String remarks = "物品";
        List<String> subsInfo = userOrderMapper.selectOrderSubsInfo(orderId);
        if (!CollectionUtils.isEmpty(subsInfo)) {
            StringBuilder builder = new StringBuilder();
            for (String s : subsInfo) {
                String[] prodString = s.split("\\|");
                String remarkSub = prodString[0];
                builder.append(remarkSub);
                builder.append("|");
            }
            String s = builder.substring(0, builder.length() - 1);
            remarks = s;
        }
        UserOrder userOrder = userOrderMapper.selectById(orderId);
        Integer tradeType = userOrder.getTradeType();
        int fastOrder = userOrder.getFastOrder();
        int fastGrade = userOrder.getFastGrade();
//        if(tradeType!=null){
//            inOrOut = tradeType;
//            if(tradeType==2){
//                inOrOut = 1;
//            }
//        }else {
//            inOrOut=0;
//        }
        BigDecimal orderMoney = userOrder.getRealMoney().add(userOrder.getProfitMoney());
        logger.info("下单后进行奖励,订单ID:{},用户ID:{},订单金额:{}", orderId, userId, orderMoney);

        //orderMoney = orderMoney.add(profitMoney);

        // todo 1.给自己的交易明细写一笔
        Date date = new Date(userRewardEvent.getTimeStamp());
        UserRankDetail selfDetail = new UserRankDetail();
        selfDetail.setId(UUIDGenerator.generate());
        selfDetail.setCreateTime(date);
        selfDetail.setRemark("购买 " + remarks);
        selfDetail.setProfitInfo("购买 " + remarks);
        BigDecimal sendMoney = userOrder.getEndMoney().add(userOrder.getProfitMoney());
        selfDetail.setGrowthValue(sendMoney.doubleValue());
        int k = 0;
        int profit = userRewardEvent.getProfit();
        selfDetail.setUpMode(0);
        if (profit == 1) {
            k = 1;
            selfDetail.setUpMode(UpMode.yu_e_buy);
            selfDetail.setRemark("收益,兑换:" + remarks);
            selfDetail.setGrowthValue(userOrder.getProfitMoney().doubleValue());
            selfDetail.setProfitInfo("收益,兑换:" + remarks);
        }
        selfDetail.setFromUserId(userId);
        selfDetail.setUserId(userId);
        selfDetail.setOrdersId(orderId);


        UserRankInfo userRankInfo = userRankMapper.selectUserRankTabs(userId);
        // 返利 上级
        userRankInfo.setGrowth(orderMoney);
        UserRank userRank = new UserRank();
        userRank.setId(userRankInfo.getUserRankId());
        userRank.setRankId(userRankInfo.getRankId());
        Integer selfRankNo = userRankInfo.getRankNo();
        Double oldValue = userRankInfo.getGrowth().doubleValue();
        Double bill = orderMoney.doubleValue();
        if (fastOrder == 1) {
            userRank.setMyGrowthValue(oldValue + fastGrade);
        } else {
            userRank.setMyGrowthValue(oldValue + sendMoney.doubleValue());
        }
        userRank.setUpdateTime(date);

        boolean recode = false;
        int grades = userRankInfo.getRankNo();
        List<UserRankDso> rankTabs = userRankMapper.selectAllRankTabs();

        for (int i = 0; i < rankTabs.size(); i++) {
            if (userRank.getRankId().equals(rankTabs.get(i).getRankId())) {
                Double myGrowthValue = userRank.getMyGrowthValue();
                BigDecimal rankPay = rankTabs.get(i).getRankPay();
                if (rankPay.compareTo(BigDecimal.ZERO) > 0 && rankPay.compareTo(BigDecimal.valueOf(myGrowthValue)) < 0) {
                    int rankNum = rankTabs.get(i).getRankNum();
                    if (rankNum < 3) {
                        String nowId = rankTabs.get(i + 1).getRankId();
                        userRank.setRankId(nowId);
                        recode = true;
                        grades += 1;
                    }
                }
            }
        }


        // todo 1.1 把用户自己的交易明细保存
//        BigDecimal profitMoney = userOrder.getProfitMoney();
//        BigDecimal payMoney = userOrder.getPayMoney();
//        if(payMoney!=null&& payMoney.compareTo(BigDecimal.ZERO)>0){
//            UserRankDetail stockDetail = new UserRankDetail();
//            stockDetail.setId(UUIDGenerator.generate()).setCreateTime(date);
//            stockDetail.setFromUserId(userId);
//            stockDetail.setUserId(userId);
//            stockDetail.setOrdersId(orderId);
//            stockDetail.setGrowthValue(payMoney.doubleValue());
//            stockDetail.setUpMode(UpMode.down_cang);
//            stockDetail.setRemark("货仓,兑换:" + remarks);
//            userRankMapper.insertUserRankDetail(stockDetail);
//        }

//        if(profitMoney!=null&& profitMoney.compareTo(BigDecimal.ZERO)>0){
//            UserRankDetail profitDetail = new UserRankDetail();
//            profitDetail.setId(UUIDGenerator.generate()).setCreateTime(date);
//            profitDetail.setFromUserId(userId);
//            profitDetail.setUserId(userId);
//            profitDetail.setOrdersId(orderId);
//            profitDetail.setGrowthValue(profitMoney.doubleValue());
//            profitDetail.setUpMode(UpMode.yu_e_buy);
//            profitDetail.setRemark("收益,兑换:" + remarks);
//            userRankMapper.insertUserRankDetail(profitDetail);
//        }

        userRankMapper.insertUserRankDetail(selfDetail);
        userRankMapper.updateByIdSelective(userRank);

        if (recode) {
            UserRankHistory rankHistory = new UserRankHistory();
            rankHistory.setId(UUIDGenerator.generate())
                    .setUserId(userId).setCreateTime(date)
                    .setRankId(userRank.getRankId()).setRankNumber(grades)
                    .setNickName(userRankInfo.getNickName());
            userRankMapper.insertUserRankHistory(rankHistory);

        }

        // todo 2.查找用户的父级
        UserInvite parentInvite = getUserParentInvite(userId);
        UserExchangeRate userExchangeRate = new UserExchangeRate();
        userExchangeRate.setId(UUIDGenerator.generate());
        userExchangeRate.setUserId(userId);
        userExchangeRate.setOrderId(orderId);
        userExchangeRate.setStates(0);
        userExchangeRate.setCreateTime(new Date());
        logger.info("下单后进行奖励,<UserExchangeRate>表,数据:{}", userExchangeRate);


        ArrayList<SelfAndUpEvent> events = new ArrayList<>();


        // todo 2.1 有上级
        if (parentInvite != null) {
            // todo 直接一级的UserId
            String up1UserId = parentInvite.getFromUser();
            UserRankInfo userRankTabs = userRankMapper.selectUserRankTabs(up1UserId);
            int rankNo = userRankTabs.getRankNo();
            // todo 2.2 只有一次奖励
            Map<String, Object> map = new HashMap<>();
            if (rankNo <= selfRankNo) {
//                orderMoney = orderMoney.add(userOrder.getProfitMoney());
                orderMoney = orderMoney.divide(BigDecimal.valueOf(2), RoundingMode.HALF_UP);
                if (inOrOut == 1) {
                    map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, remarks, userRankTabs.getSeaRankRate(), selfRankNo, orderId, true, userRankInfo, userRankInfo, k);
                } else {
                    map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, remarks, userRankTabs.getRankRate(), selfRankNo, orderId, true, userRankInfo, userRankInfo, k);
                }
                userExchangeRate.setDirectRate(BigDecimal.ZERO.doubleValue());
            } else {
                if (inOrOut == 1) {
                    map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, remarks, userRankTabs.getSeaRankRate(), selfRankNo, orderId, false, userRankInfo, userRankInfo, k);
                } else {
                    map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, remarks, userRankTabs.getRankRate(), selfRankNo, orderId, false, userRankInfo, userRankInfo, k);
                }
                BigDecimal rate = (BigDecimal) map.get("rate");
                userExchangeRate.setDirectRate(rate.doubleValue());
            }
            userExchangeRate.setDirectUserId(up1UserId);

            UserInvite parentInviteL4 = getUserParentInvite(up1UserId);
            if (rankNo != 3) {
                String up2UserId = parentInviteL4.getFromUser();
                UserRankInfo userRankTabs2 = userRankMapper.selectUserRankTabs(up2UserId);
                Map<String, Object> map1;
                if (rankNo <= selfRankNo) {
                    if (inOrOut == 1) {
                        userRankTabs.setMiddle(1);
                        map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getSeaRankRate(), rankNo, orderId, true, userRankInfo, userRankTabs, k);
                    } else {
                        userRankTabs.setMiddle(0);
                        map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getRankRate(), rankNo, orderId, true, userRankInfo, userRankTabs, k);
                    }
                    userExchangeRate.setTopRate(BigDecimal.ZERO.doubleValue());
                } else {
                    if (rankNo >= userRankTabs2.getRankNo()) {
                        if (inOrOut == 1) {
                            userRankTabs.setMiddle(1);
                            map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getSeaRankRate(), rankNo, orderId, true, userRankInfo, userRankTabs, k);
                        } else {
                            userRankTabs.setMiddle(0);
                            map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getRankRate(), rankNo, orderId, true, userRankInfo, userRankTabs, k);
                        }
                        userExchangeRate.setTopRate(BigDecimal.ZERO.doubleValue());
                    } else {
                        if (inOrOut == 1) {
                            userRankTabs.setMiddle(1);
                            map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getSeaRankRate(), rankNo, orderId, false, userRankInfo, userRankTabs, k);
                        } else {
                            userRankTabs.setMiddle(0);
                            map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), remarks, userRankTabs2.getRankRate(), rankNo, orderId, false, userRankInfo, userRankTabs, k);
                        }
                        BigDecimal rate2 = (BigDecimal) map1.get("rate");
                        userExchangeRate.setTopRate(rate2.doubleValue());
                    }
                }
                userExchangeRate.setTopUserId(up2UserId);
            }
        }
        if (!CollectionUtils.isEmpty(events)) {
            for (SelfAndUpEvent event : events) {
                logger.info("下单后进行奖励,<SelfAndUpEvent>中转数据,数据:{}", event);
                //applicationContext.publishEvent(event);
            }
        }
        userExchangeRateMapper.insert(userExchangeRate);
        logger.info("下单后进行奖励,<UserExchangeRate>表数据操作结束了,数据:{}", userExchangeRate);
    }


    public UserInvite getUserParentInvite(String thisId) {
        List<UserInvite> invites = userInviteMapper.selectUserInviteByUserId(thisId);
        if (!CollectionUtils.isEmpty(invites)) {
            UserInvite userInvite = invites.get(0);
            return userInvite;
        }
        return null;
    }


    public UserProfit getUserProfit(String userId) {
        List<UserProfit> userProfits = userProfitMapper.selectByUserId(userId);
        if (!CollectionUtils.isEmpty(userProfits)) {
            UserProfit userProfit = userProfits.get(0);
            return userProfit;
        }
        return null;
    }


    public Map<String, Object> handleRankProfitDetail(Date date, String up1UserId, String userId, BigDecimal orderMoney,
                                                      String remarks, Double rankRate, Integer selfRankNo, String orderId, boolean flag, UserRankInfo root, UserRankInfo self, int k) {
        boolean points = flag;
        UserRankDetail up4 = new UserRankDetail();
        up4.setId(UUIDGenerator.generate());
        up4.setCreateTime(date);

        up4.setUserId(up1UserId);
        up4.setFromUserId(userId);
        up4.setOrdersId(orderId);
        BigDecimal t1 = BigDecimal.ONE;
        if (!flag) {
            t1 = t1.subtract(BigDecimal.valueOf(rankRate));
        }


        BigDecimal up1Bill = orderMoney.multiply(t1).setScale(2,RoundingMode.HALF_UP);
        up4.setUpMode(1);
        up4.setGrowthValue(up1Bill.doubleValue());
        if (flag) {
            up4.setUpMode(9);
            up4.setGrowthValue(orderMoney.doubleValue());
        }
        up4.setRemark("购买" + remarks);

        UserRankInfo up1UserRankInfo = userRankMapper.selectUserRankTabs(up1UserId);


        if (!flag) {
            StringBuilder sb = new StringBuilder();
            if (root.equals(self)) {// 1,2
                String nickName = self.getNickName();
                String rankName = self.getRankName();
                sb.append(rankName).append(" ").append(nickName);
                BigDecimal of = BigDecimal.valueOf((1 - rankRate) * 100).setScale(0, RoundingMode.HALF_UP);
                if (k == 0) {
                    sb.append("消费").append(orderMoney).append("元(不包含运税费).");
                    sb.append("您当前是").append(up1UserRankInfo.getRankName())
                            .append(",").append("获得粉丝消费金额的");

                    sb.append(of).append("%,").append(orderMoney)
                            .append("×").append(of).append("%=")
                            .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                } else {
                    sb.append("兑换物品,消费").append(orderMoney).append("元.");
                    sb.append("您当前是").append(up1UserRankInfo.getRankName())
                            .append(",").append("获得粉丝消费金额的");
                    sb.append(of).append("%,").append(orderMoney)
                            .append("×").append(of).append("%").append("=")
                            .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                }

            } else { // 1,2,3
                if (k == 0) { // 消费
                    BigDecimal growth = root.getGrowth();
                    sb.append(root.getRankName()).append(" ").append(root.getNickName());
                    sb.append("消费").append(growth.setScale(2,RoundingMode.HALF_UP)).append("元(不包含运税费),");
                    sb.append(self.getNickName()).append("获得收益");

                    if (self.getMiddle() == 1) {
                        BigDecimal of = BigDecimal.valueOf((1 - self.getSeaRankRate())*100).setScale(0, RoundingMode.HALF_UP);
                        sb.append(growth).append("×").append(of).append("%=")
                                .append(orderMoney.setScale(2,RoundingMode.HALF_UP)).append("元.");
                    } else {
                        BigDecimal of = BigDecimal.valueOf((1 - self.getRankRate())*100).setScale(0, RoundingMode.HALF_UP);
                        sb.append(growth).append("×").append(of).append("%=")
                                .append(orderMoney).append("元.");
                    }

                    sb.append("您当前是").append(up1UserRankInfo.getRankName())
                            .append(",").append("获得粉丝收益金额的");
                    if (self.getMiddle() == 1) {
                        BigDecimal of = BigDecimal.valueOf((1 - up1UserRankInfo.getSeaRankRate())*100).setScale(0, RoundingMode.HALF_UP);
                        sb.append(of).append("%,").append(orderMoney)
                                .append("×");
                        sb.append(of).append("%").append("=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                    } else {
                        int v = (int)((1 - up1UserRankInfo.getRankRate()) * 100);
                        BigDecimal of = BigDecimal.valueOf((1 - up1UserRankInfo.getRankRate())*100).setScale(0, RoundingMode.HALF_UP);

                        sb.append(of).append("%,").append(orderMoney)
                                .append("×");
                        sb.append(of).append("%").append("=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                    }
                } else {
                    BigDecimal growth = root.getGrowth();
                    sb.append(root.getRankName()).append(" ").append(root.getNickName());
                    sb.append("兑换物品,消费").append(growth).append("元(不包含运税费),");
                    sb.append(self.getNickName()).append("获得收益");

                    if (self.getMiddle() == 1) {
                        BigDecimal of = BigDecimal.valueOf((1 - self.getSeaRankRate()) * 100).setScale(0, RoundingMode.HALF_UP);
                        sb.append(growth).append("×").append(of).append("%=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元.");
                    } else {
                        BigDecimal of = BigDecimal.valueOf((1 - self.getRankRate()) * 100).setScale(0, RoundingMode.HALF_UP);
                        sb.append(growth).append("×").append(of).append("%=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元.");
                    }

                    sb.append("您当前是").append(up1UserRankInfo.getRankName())
                            .append(",").append("获得粉丝收益金额的");
                    if (self.getMiddle() == 1) {
                        
                        BigDecimal of = BigDecimal.valueOf((1 - up1UserRankInfo.getSeaRankRate()) * 100).setScale(0, RoundingMode.HALF_UP);


                        sb.append(of).append("%,").append(orderMoney)
                                .append("×");
                        sb.append(of).append("%").append("=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                    } else {
                        BigDecimal of = BigDecimal.valueOf((1 - up1UserRankInfo.getRankRate())*100).setScale(0, RoundingMode.HALF_UP);

                        sb.append(of).append("%,").append(orderMoney)
                                .append("×");
                        sb.append(of).append("%").append("=")
                                .append(up1Bill.setScale(2,RoundingMode.HALF_UP)).append("元");
                    }
                }
            }
            up4.setProfitInfo(sb.toString());
        }


        UserRank up1UserRank = new UserRank();

        up1UserRank.setId(up1UserRankInfo.getUserRankId());
        Double up1OldValue = up1UserRankInfo.getGrowth().doubleValue();

        up1UserRank.setRankId(up1UserRankInfo.getRankId());
        up1UserRank.setUpdateTime(date);
        up1UserRank.setMyGrowthValue(up1OldValue + up1Bill.doubleValue());

        boolean recode = false;
        int grade = up1UserRankInfo.getRankNo();
        List<UserRankDso> rankTabs = userRankMapper.selectAllRankTabs();
        for (int i = 0; i < rankTabs.size(); i++) {
            if (up1UserRank.getRankId().equals(rankTabs.get(i).getRankId())) {
                Double myGrowthValue = up1UserRank.getMyGrowthValue();
                BigDecimal rankPay = rankTabs.get(i).getRankPay();
                if (rankPay.compareTo(BigDecimal.ZERO) > 0 && rankPay.compareTo(BigDecimal.valueOf(myGrowthValue)) < 0) {
                    String nowId = rankTabs.get(i + 1).getRankId();
                    up1UserRank.setRankId(nowId);
                    up1UserRank.setUpdateTime(date);
                    recode = true;
                    grade += 1;
                }
            }
        }


        Integer upRankNo = up1UserRankInfo.getRankNo();
        up4.setGrowthValue(up1Bill.doubleValue());
        if (upRankNo <= selfRankNo) {
            up4.setUpMode(9);
            up1UserRank.setMyGrowthValue(orderMoney.add(up1UserRankInfo.getGrowth()).doubleValue());
            points = true;
        } else {
            if (!flag) {


                // 特权
                List<String> specUsers = customerMapper.findSpecificUser();
                if (specUsers == null) {

                    UserProfit userProfit = getUserProfit(up1UserId);
                    userProfit.setUpdateTime(date);
                    BigDecimal oldAccount = userProfit.getAccountMoney();
                    BigDecimal oldProfitMoney = userProfit.getProfitMoney();
                    userProfit.setAccountMoney(oldAccount.add(up1Bill));
                    BigDecimal nowProfitMoney = oldProfitMoney.add(up1Bill);
                    userProfit.setProfitMoney(nowProfitMoney);
                    userProfitMapper.updateByIdSelective(userProfit);
                } else {
                    if (!specUsers.contains(up1UserId)) {
                        UserProfit userProfit = getUserProfit(up1UserId);
                        userProfit.setUpdateTime(date);
                        BigDecimal oldAccount = userProfit.getAccountMoney();
                        BigDecimal oldProfitMoney = userProfit.getProfitMoney();
                        userProfit.setAccountMoney(oldAccount.add(up1Bill));
                        BigDecimal nowProfitMoney = oldProfitMoney.add(up1Bill);
                        userProfit.setProfitMoney(nowProfitMoney);
                        userProfitMapper.updateByIdSelective(userProfit);
                    }
                }


            }

        }
        userRankMapper.updateByIdSelective(up1UserRank);
        userRankMapper.insertUserRankDetail(up4);

        if (recode) {
            UserRankHistory history = new UserRankHistory();
            history.setCreateTime(date)
                    .setId(UUIDGenerator.generate())
                    .setUserId(up1UserId)
                    .setNickName(up1UserRankInfo.getNickName())
                    .setRankNumber(grade)
                    .setRankId(up1UserRank.getRankId());

            userRankMapper.insertUserRankHistory(history);
        }

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("orderMoney", up1Bill);
        if (flag) {
            hashMap.put("orderMoney", orderMoney.divide(BigDecimal.valueOf(2), RoundingMode.HALF_UP));
        }
        hashMap.put("rate", t1);
        hashMap.put("selfRankId", up1UserRank.getRankId());
        hashMap.put("point", points);
        return hashMap;
    }


}
